package org.springblade.modules.teambition.service;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.utils.RedisUtil;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.modules.teambition.config.TeambitionProperties;
import org.springblade.modules.teambition.constant.TbConstant;
import org.springblade.modules.teambition.entity.TaskStatus;
import org.springblade.modules.teambition.mapper.TaskStatusMapper;
import org.springblade.modules.teambition.res.*;
import org.springblade.modules.teambition.util.HttpUtil;
import org.springblade.modules.teambition.vo.OrderSearchVo;
import org.springblade.modules.teambition.vo.OrderVo;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class TeambitionService {

	public static final Long   EXPIRES_IN = 1 * 3600 * 1000L;
	public static final String TOKEN_APPID = "_appId";

	public static final String   TEAMBITION_TOKEN = "Teambition-token";

	@Resource
	private TeambitionProperties teambitionProperties;
	@Resource
	private RedisUtil redisUtil;
	@Resource
	private TaskStatusMapper taskStatusMapper;


	public String getAuthToken(){
		String authToken = String.valueOf(Optional.ofNullable(redisUtil.get(TEAMBITION_TOKEN)).orElse(""));
		if(StringUtil.isNotBlank(authToken)){
			return authToken;
		}
		return this.authToken();
	}


	public String authToken() {
		if (!StringUtils.hasText(teambitionProperties.getAppId()) || !StringUtils.hasText(teambitionProperties.getAppSecret())) {
			return null;
		}

//		Algorithm algorithm = Algorithm.HMAC256(teambitionProperties.getAppSecret());
//		long timestamp = System.currentTimeMillis();
//		Date issuedAt = new Date(timestamp);
//		Date expiresAt = new Date(timestamp + EXPIRES_IN);
//
//		String authToken = JWT.create()
//			.withClaim(TOKEN_APPID, teambitionProperties.getAppId())
//			.withIssuedAt(issuedAt)
//			.withExpiresAt(expiresAt)
//			.sign(algorithm);
//		TypeReference<TeambitionCommonRes<String>> ref = new TypeReference<TeambitionCommonRes<String>>(){};
//		TeambitionCommonRes<String> res = JSON.parseObject(sign, ref);
//		String authToken = res.getData();
		String appId = teambitionProperties.getAppId();
		String appSecret = teambitionProperties.getAppSecret();
		Algorithm algorithm = Algorithm.HMAC256(appSecret);
		long timestamp = System.currentTimeMillis();
		Date issuedAt = new Date(timestamp);
		Date expiresAt = new Date(timestamp + EXPIRES_IN);

		String authToken = JWT.create()
			.withClaim(TOKEN_APPID, appId)
			.withIssuedAt(issuedAt)
			.withExpiresAt(expiresAt)
			.sign(algorithm);
				redisUtil.set(TEAMBITION_TOKEN,authToken,EXPIRES_IN, TimeUnit.MILLISECONDS);
		return authToken;
	}

	public List<Map<String,Object>> getProjectList(){
		ParameterizedTypeReference<TeambitionCommonRes<List<Map<String,Object>>>> responseBodyType = new ParameterizedTypeReference<TeambitionCommonRes<List<Map<String,Object>>>>() {
		};
		String authToken = this.authToken();
		System.out.println("authtoken==="+authToken);
		TeambitionCommonRes<List<Map<String,Object>>> TeambitionCommonRes = HttpUtil.doGet( "https://open.teambition.com/api/v3/project/query", responseBodyType, authToken, teambitionProperties.getOrgId());
		return TeambitionCommonRes.getResult();
	}


	public List<TaskRes> getTaskList(){
		String projectId = teambitionProperties.getProjectId();
		ParameterizedTypeReference<TeambitionCommonRes<List<TaskRes>>> responseBodyType = new ParameterizedTypeReference<TeambitionCommonRes<List<TaskRes>>>() {
		};
		String url = TbConstant.PROJECT_TASK_LIST_URL.replace("PROJECT_ID",projectId);
		String authToken = this.authToken();
		HashMap<String, Object> variables = new HashMap<>();
		variables.put("pageSize",200);
		TeambitionCommonRes<List<TaskRes>> TeambitionCommonRes = HttpUtil.doGet(variables, url, responseBodyType, authToken, teambitionProperties.getOrgId());
		return TeambitionCommonRes.getResult();
	}

	public List<Map<String,Object>> getTaskList2(String url){
		ParameterizedTypeReference<TbPageQueryRes<List<Map<String,Object>>>> responseBodyType = new ParameterizedTypeReference<TbPageQueryRes<List<Map<String,Object>>>>() {
		};
		String authToken = this.authToken();
		System.out.println("authtoken==="+authToken);
		HashMap<String, Object> variables = new HashMap<>();
		variables.put("pageSize",100);
		TbPageQueryRes<List<Map<String,Object>>> TeambitionCommonRes = HttpUtil.doGet(variables, url, responseBodyType, authToken, teambitionProperties.getOrgId());
		return TeambitionCommonRes.getResult();
	}

	public IPage<TaskRes> orderList(OrderVo orderVo, Query query) {
		List<TaskRes> taskList = this.getTaskList();
		List<TaskRes> collect = taskList.stream().filter(x -> StringUtil.isBlank(x.getParentTaskId())).collect(Collectors.toList());
		if(StringUtil.isNotBlank(orderVo.getContent())){
			collect = collect.stream().filter(x->x.getContent().contains(orderVo.getContent())).collect(Collectors.toList());
		}
		List<TaskStatusRes> taskStatusList = getAllStatusList();
		List<TaskRes> collects = collect.stream().skip((long) query.getSize() * (query.getCurrent() - 1)).limit(query.getSize()).peek(x-> extracted(x,taskStatusList)).collect(Collectors.toList());
		IPage<TaskRes> page = new Page<>(query.getCurrent(), query.getSize());
		// 设置总记录数
		page.setTotal(collect.size());
		for (TaskRes taskRes : collects) {
			taskRes.extractedFields();
		}
		page.setRecords(collects);
		return page;
	}

	private void extracted(TaskRes y,List<TaskStatusRes> taskStatusList) {
		String statusName = taskStatusList.stream().filter(x -> x.getId().equals(y.getTfsId())).findFirst().map(TaskStatusRes::getName).orElse("");
		y.setTfsTag(statusName);
		y.setTaskDateRange(y.getStartDate()+"-"+y.getDueDate());
	}

	public TaskRes orderDetail(OrderVo orderVo) {
		ParameterizedTypeReference<TeambitionCommonRes<List<TaskRes>>> responseBodyType = new ParameterizedTypeReference<TeambitionCommonRes<List<TaskRes>>>() {
		};
		String authToken = this.authToken();
		String url = "https://open.teambition.com/api/v3/task/query";
		HashMap<String, Object> param = new HashMap<>();
		param.put("taskId",orderVo.getId());
		List<TaskStatusRes> allStatusList = getAllStatusList();
		TeambitionCommonRes<List<TaskRes>> TeambitionCommonRes = HttpUtil.doGet(param, url, responseBodyType, authToken, teambitionProperties.getOrgId());
		return Optional.ofNullable(TeambitionCommonRes.getResult()).map(x->{
			extracted(x.get(0),allStatusList);
			return x.get(0);
		}).orElse(null);
	}

	public List<TaskStatusRes> getTaskStatusList(){
		return getAllStatusList();
	}

	public List<TaskStatusRes> getAllStatusList(){
//		String url = "https://open.teambition.com/api/v3/project/675f9079f8deb1c896efdfb3/taskflowstatus/search";
		String url = TbConstant.PROJECT_TASK_STATUS_LIST_URL.replace("PROJECT_ID",teambitionProperties.getProjectId());
		HashMap<String, Object> param = new HashMap<>();
		param.put("pageSize",100);
		ParameterizedTypeReference<TeambitionCommonRes<List<TaskStatusRes>>> responseBodyType = new ParameterizedTypeReference<TeambitionCommonRes<List<TaskStatusRes>>>() {
		};
		String authToken = this.authToken();
		TeambitionCommonRes<List<TaskStatusRes>> TeambitionCommonRes = HttpUtil.doGet(param, url, responseBodyType, authToken, teambitionProperties.getOrgId());
		List<TaskStatusRes> result = TeambitionCommonRes.getResult();
		List<TaskStatusRes> collect = result.stream().filter(x -> {
			if (StringUtil.isNotBlank(teambitionProperties.getTaskFlowId())) {
				return teambitionProperties.getTaskFlowId().equals(x.getTaskflowId());
			}
			return true;
		}).collect(Collectors.toList());
		return collect;
	}

	public TaskRes searchOrder(OrderSearchVo orderVo) {
		if (StringUtil.isBlank(orderVo.getSearchContent())) {
			throw new ServiceException("请输入合同编号");
		}

		List<TaskRes> taskList = this.getTaskList();
		List<TaskRes> collect = taskList.stream().filter(x -> StringUtil.isBlank(x.getParentTaskId())).collect(Collectors.toList());
		for (TaskRes taskRes : collect) {
			taskRes.extractedFields();
		}
		return collect.stream().filter(x -> x.getOrderNo().contains(orderVo.getSearchContent())).peek(x -> {
			this.extracted(x, getTaskStatusList());
			x.setActList(this.getOrderProcess(x.getId()));
		}).findFirst().orElse(null);
	}


	public List<TaskActivityRes.ActionItem> getOrderProcess(String taskId){
//		String url = "https://open.teambition.com/api/v3/task/TASK_ID/activity/list";
		String url = TbConstant.TASK_ACTIVITY_LIST_URL.replace("TASK_ID", taskId);
		ParameterizedTypeReference<TeambitionCommonRes<List<TaskActivityRes>>> responseBodyType = new ParameterizedTypeReference<TeambitionCommonRes<List<TaskActivityRes>>>() {
		};
		String authToken = this.authToken();
		HashMap<String, Object> param = new HashMap<>();
		param.put("pageSize",100);
		TeambitionCommonRes<List<TaskActivityRes>> res = HttpUtil.doGet(param, url, responseBodyType, authToken, teambitionProperties.getOrgId());
		return res.getResult().stream().peek(TaskActivityRes::extractedItems).map(TaskActivityRes::getStep).filter(Objects::nonNull).collect(Collectors.toList());
	}

	public List<TaskStepRes> getTaskStatusSteps() {
		List<TaskStatus> taskStatuses = taskStatusMapper.selectList(TaskStatus.gw().orderByAsc(TaskStatus::getStep));
		return taskStatuses.stream().map(x -> {
			TaskStepRes taskStatusRes = new TaskStepRes();
			taskStatusRes.setId(x.getId());
			taskStatusRes.setName(x.getStatusLabel() + "/" + x.getStatusLabelEn());
			taskStatusRes.setStepName(x.getStatusLabel());
			taskStatusRes.setStepNameEn(x.getStatusLabelEn());
			return taskStatusRes;
		}).collect(Collectors.toList());
	}
}
